1 module hip.hipaudio.backend.avaudio.player;
2 
3 version(iOS):
4 public import hip.hipaudio.backend.avaudio.clip;
5 public import hip.hipaudio.backend.avaudio.source;
6 public import hip.audio_decoding.audio;
7 import avaudioengine;
8 import avaudiomixernode;
9 import avaudioplayernode;
10 import hip.hipaudio.audio;
11 import hip.error.handler;
12 
13 class HipAVAudioPlayer : IHipAudioPlayer
14 {
15     AVAudioEngine engine;
16     AVAudioPlayerNode playerNode;
17     AVAudioMixerNode mixerNode;
18 
19     private static AudioConfig config;
20     package static AudioConfig getAudioConfig(){return config;}
21 
22     /**
23     *   For getting better debug information, you need to run this application on Visual Studio.
24     *   The debug messages actually appears inside the `Output` window.
25     */
26     public this(AudioConfig cfg)
27     {
28         HipAVAudioPlayer.config = cfg;
29         engine = AVAudioEngine.alloc.init;
30         mixerNode = AVAudioMixerNode.alloc.init;
31         playerNode = AVAudioPlayerNode.alloc.init;
32 
33         engine.attachNode(mixerNode);
34         engine.attachNode(playerNode);
35         AVAudioFormat format = fromConfig(cfg);
36         engine.connect(cast(AVAudioNode)playerNode, cast(AVAudioNode)engine.outputNode, format);
37 
38         engine.prepare();
39         NSError err;
40         if(!engine.start(&err))
41             ErrorHandler.assertExit(false, "Could not initialize AVAudioEngine: "~err.toString);
42     }
43 
44     public static AVAudioFormat fromConfig(immutable AudioConfig cfg)
45     {
46         import hip.util.conv;
47         AVAudioCommonFormat format;
48         switch(cfg.format)
49         {
50             case AudioFormat.signed16Big:
51             case AudioFormat.signed16Little:
52                 format = AVAudioCommonFormat.PCMFormatInt16;
53                 break;
54             case AudioFormat.signed32Big:
55             case AudioFormat.signed32Little:
56                 format = AVAudioCommonFormat.PCMFormatInt32;
57                 break;
58             case AudioFormat.float32Big:
59             case AudioFormat.float32Little:
60                 format = AVAudioCommonFormat.PCMFormatFloat32;
61                 break;
62             default:
63                 ErrorHandler.assertExit(false, "AVAudioEngine Does not support the current bit depth");
64                 break;
65         }
66         AVAudioFormat fmt = AVAudioFormat.alloc.initWithCommonFormat(format, cfg.sampleRate, cfg.channels, interleaved: cfg.channels == 2 ? true : false);
67         ErrorHandler.assertLazyExit(fmt !is null, "Could not create audio format with config " ~ cfg.to!string);
68         return fmt;
69     }
70 
71     public bool play_streamed(AHipAudioSource src){return src.play_streamed();}
72 
73     public AHipAudioSource getSource(bool isStreamed){return new HipAVAudioSource(this);}
74     public IHipAudioClip getClip(){return new HipAVAudioClip(new HipAudioDecoder(), HipAudioClipHint(config.channels, config.sampleRate, false, true));}
75 
76     public IHipAudioClip loadStreamed(string audioName, uint chunkSize)
77     {
78         ErrorHandler.assertExit(false, "AVAudioPlayer Player does not support chunked decoding");
79         return null;
80     }
81     public void updateStream(AHipAudioSource source){}
82 
83     public void onDestroy()
84     {
85     }
86     public void update(){}
87 }